<?php
/**
 * Handles thrown exceptions and decides how to present them to a user.
 * @author jan
 */
class YoseminExceptionHandler {

    /** @var Exception */
    private $exception;
    /** @var Controller */
    private $controller;
    private $fallBackUrl;
    
    public function __construct(&$controller, $exception) {
        $this->exception = $exception;
        $this->controller = $controller;
    }

    public static function getDbErrorCode($exception) {
        if ($exception instanceof PDOException) {
            if (is_array($exception->errorInfo) && count($exception->errorInfo) > 1) {
                return $exception->errorInfo[1];
            }
        }
        return NULL;
    }

    public static function isRowReferencedError($exception) {
        $dbErrorCode = self::getDbErrorCode($exception);
        return $dbErrorCode == MysqlErrorCodes::$ERROR_ROW_IS_REFERENCED_2;
    }

    public static function isDuplicateEntryError($exception) {
        $dbErrorCode = self::getDbErrorCode($exception);
        return $dbErrorCode == MysqlErrorCodes::$ERROR_DUP_ENTRY;
    }

    public function handle() {
        $redirect = FALSE;
        
        $msg = Messages::instance();

        if (self::isRowReferencedError($this->exception)) {
            Kohana::log('info', 'Trying to delete a record, that is still referenced in file ' .
                    $this->exception->getFile() . ':' . $this->exception->getLine() . '.');
            $msg->error('error.db-rowIsReferenced');
        }
        else if (self::isDuplicateEntryError($this->exception)) {
            Kohana::log('info', 'Trying to save a record, with duplicate value of a unique key. In file ' .
                    $this->exception->getFile() . ':' . $this->exception->getLine() . '.');
            // This error should be handled
            die ($this->exception);
            $msg->error('error.db-duplicateEntry');
        }
        
        if ($this->exception instanceof LogicException) {
        	$msg->error($this->exception->getMessage());
        	$this->controller->redirectBack();
        }

        // If we have some error messages, redirect.
        if ($msg->hasErrors()) {
            if ($this->fallBackUrl) {
                $this->controller->redirect($this->fallBackUrl);
            }
            else {
                $this->controller->redirectBack();
            }
        }

        Kohana::log('error', $this->exception);

        // If we are not able to handle this exception, throw it away.
        throw $this->exception;
    }
}

/**
 * MySQL error codes from
 * http://dev.mysql.com/doc/refman/5.1/en/error-messages-server.html
 */
class MysqlErrorCodes {

    /* Message: Cannot delete or update a parent row: a foreign key constraint fails (%s). */
    public static $ERROR_ROW_IS_REFERENCED_2 = 1451;

    /* Message: Duplicate entry '%s' for key %d. */
    public static $ERROR_DUP_ENTRY = 1062;
}
